﻿using System;

namespace Effects.Effects.Tools
{
    /// <summary>
    ///  Implementation of square wave oscillator
    /// </summary>
    /// <remarks>
    ///  In fact this class doesn't act exactly as ideal square wave ocillator. The reason is that people are used to the electric-circuit-like square wave 
    ///  oscillators that have continuous graph. So combinatian of ideal square wave and sine wave is used.
    /// </remarks>
    public class SquareOscilator : Oscillator
    {
        /// <summary>
        ///  Gets ocillator's value at given time.  Overridden to behave as square wave oscillator. 
        /// </summary>
        /// <param name="time"> time of the oscilation </param>
        /// <returns> Value at given time. </returns>
        public override double Amplitude(double time)
        {
            //time = time % period;
            while (time > period)
                time -= period;
            /*
            double depth = 0;
            if (time <= period / 4)
            {
                depth = time / (period / 4);
            }
            else if (time <= period / 2)
            {
                depth = (period / 2 - time) / (period / 4);
            }
            else if (time <= 3 * period / 4)
            {
                depth = (time - period / 2) / (period / 4);
            }
            else
            {
                depth = (period - time) / (period / 4);
            }

            // combines constant function and sine, based on time/period 
            if (time <= period / 2)
            {
                return (depth + (1 - depth) * Math.Sin(time * 2 * Math.PI) + 1) / 2;
            }
            else
            {
                return (-depth + (1 - depth) * Math.Sin(time * 2 * Math.PI) + 1) / 2;
            }*/

            double ret = Math.Sin(time * 2 * Math.PI / period);
            ret = Math.Sign(ret) * Math.Pow(Math.Abs(ret), 1F / 3F);
            return ret;
        }

        /// <summary>
        ///  Makes stepTime advance of oscillator's time and returns current value of oscillation.  Overridden to behave as square wave oscillator.
        /// </summary>
        /// <param name="stepTime"> Length of a step that oscillator advances in time. </param>
        /// <returns> Current value of an oscillator after the step.</returns>
        public override double Step(double stepTime)
        {
            time += stepTime;
            //time %= period;
            if (time > period)
                time -= period;

            return Amplitude(time);
        }
    }
}